package com.bree.erp.jsf.datatable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.log4j.Logger;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

import com.bree.erp.entity.BalanceId;
import com.bree.erp.entity.CrudId;
import com.bree.erp.service.Crud;

public class LazyBreeDataModel  <T extends CrudId<ID>, S extends Crud<T, ID>, ID> extends LazyDataModel<T> {

	private static Logger LOG = Logger.getLogger(LazyBreeDataModel.class);
	
	private static final long serialVersionUID = 1L;
	
	private S service;
	private ID sample;

	public LazyBreeDataModel(S service, ID sample) {
		this.service = service;
		this.sample = sample;
	}
	
	@Override
	public T getRowData(String rowKey) {
		
		ID id = parseId(rowKey, sample);
		
		return service.read(id);
	}
	

    @SuppressWarnings("unchecked")
	private ID parseId(String rowKey, ID type){ 
    		
    	if(type instanceof Long) {
    		return (ID) (Long) Long.parseLong(rowKey);
    	}
    	
    	if(type instanceof String) {
    		return (ID) rowKey;
    	}
    	
    	if(type instanceof BalanceId) {
    		String[] arr = rowKey.split(":");
    		String warehouse = arr[0];
    		Long partUnit = Long.parseLong(arr[1]);
    		BalanceId balanceId = new BalanceId(warehouse, partUnit);
    		return (ID) balanceId;
    	}
    
		return null;
	}

	@Override
    public Object getRowKey(T inventory) {
    	return inventory.getId();
    }

    @Override
    public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
    	
    	List<T> items = new ArrayList<T>();
    	
        PropertyUtilsBean utilsBean = new PropertyUtilsBean();
        
        LOG.debug(">>>>> START: LOAD <<<<<" + (filters == null ? "null" : filters.size()) + " [" + service.getClass() + "]");
    	
    	for(T item : service.list()) {

            boolean match = true;
 
            if (filters != null) {
                for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                    try {
                        String filterProperty = it.next();
                        Object filterValue = filters.get(filterProperty);
                        
                        String fieldValue = String.valueOf(utilsBean.getProperty(item, filterProperty)).toLowerCase(); 
                        		//String.valueOf(item.getClass().getDeclaredField(filterProperty).get(item));
                        
                        LOG.debug("  field: " + fieldValue + "; filter: " + filterValue);
                        
                        if(filterValue == null || fieldValue.contains(filterValue.toString().toLowerCase())) {
                            match = true;
	                    }
	                    else {	
	                    	match = false;
	                        break;
	                    }
                    } catch(Exception e) {
                    	
                    	LOG.error(e.getMessage(), e);
                        match = false;
                    }
                }
            }
 
            if(match) {
                items.add(item);
            }
    	}
    	
        //sort
        if(sortField != null) {
            Collections.sort(items, new LazySorter<T>(sortField, sortOrder));
        }
 
        //rowCount
        int dataSize = items.size();
        this.setRowCount(dataSize);
 
        //paginate
        if(dataSize > pageSize) {
            try {
                return items.subList(first, first + pageSize);
            }
            catch(IndexOutOfBoundsException e) {
                return items.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            return items;
        }
    }


}
